#include <fcntl.h>           /* For O_* constants */
#include <sys/stat.h>        /* For mode constants */
#include <semaphore.h>

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <signal.h>
#include <pthread.h>

/*
>abcd
abcd

>cdasdfs
cdasdfs

>dssssssssssssssssssssssssssss
dssssssssssssssssssssssssssss
 *
 */

sem_t sem_r,sem_w;
char *shmaddr;

void destroysem(int sig){
   sem_destroy(&sem_r);
   sem_destroy(&sem_w);
   exit(0);
}

void *readmem(void *arg){
    while(1){
        sem_wait(&sem_r);
        printf("%s\n",shmaddr);
        sem_post(&sem_w);
    }
}

int main(){
   key_t key;
   int shmid;

   //捕捉Ctrl + C信号 销毁无名信号灯后再退出
   struct sigaction act;
   act.sa_handler = destroysem;
   act.sa_flags = 0;
   sigemptyset(&act.sa_mask);
   sigaction(SIGINT,&act,NULL);

   //初始化key
   key = ftok(".",100);
   if(key<0){
       perror("ftok");
       return 0;
   }

   //获取共享内存id
   shmid = shmget(key,500,0666|IPC_CREAT);
   if(shmid<0){
       perror("shmget");
       return 0;
   }

   //将内核空间映射到用户空间
   shmaddr = shmat(shmid,NULL,0);
   
   //初始化 读信号量 初始值为0
   sem_init(&sem_r,0,0);
   //初始化 写信号量 初始值为1
   sem_init(&sem_w,0,1);

   //创建子线程
   pthread_t tid;
   pthread_create(&tid,NULL,readmem,NULL);
   
   //主线程
   while(1){
        sem_wait(&sem_w);
		//按理 > 不会立即输出，但测试效果是立即输出的，应该是后面的fgets函数起了效果
		printf(">");
        fgets(shmaddr,500,stdin);
        sem_post(&sem_r);
   }

}


